package com.mxpio.erp.plan.controller;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;

import com.mxpio.erp.common.enums.CommonEnums;
import com.mxpio.erp.common.enums.PlanEnums;
import com.mxpio.erp.common.plan.entity.*;
import com.mxpioframework.cache.provider.CacheProvider;
import com.mxpioframework.common.util.SpringUtil;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.policy.CrudContext;
import com.mxpioframework.jpa.policy.impl.SmartCrudPolicyAdapter;
import com.mxpioframework.jpa.query.Operator;
import com.mxpioframework.system.service.SnRuleService;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.mxpio.erp.common.enums.OrderStatusEnums;
import com.mxpio.erp.common.plan.service.MpsVersionService;
import com.mxpio.erp.common.sales.entity.SalesOrderLine;
import com.mxpio.erp.plan.mrp.Context;
import com.mxpio.erp.plan.mrp.service.LrpCoreService;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.query.Criteria;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Tag(name = "MpsVersionController", description = "主计划版本接口")
@RestController
@RequestMapping("/erp/plan/mps/")
public class MpsVersionController {

	@Autowired
	private MpsVersionService mpsVersionService;
	@Autowired
	private LrpCoreService lrpCoreService;
	@Autowired
	private CacheProvider cacheProvider;

	public static final String MRP_CACHE_KEY = "MRP_IN_PROGRESSING";
	@GetMapping("mrp")
	@Operation(summary = "测试MRP", description = "测试MRP", method = "GET")
	@Transactional
	public Result<Object> test(){
		try {
			String o = (String) cacheProvider.get(MRP_CACHE_KEY);
			if (StringUtils.isBlank(o)){
				cacheProvider.set(MRP_CACHE_KEY,MRP_CACHE_KEY,180);
				log.info("MRP:===========Job start============");
				List<MpsVersion> effectiveMpsVersions = JpaUtil.linq(MpsVersion.class)
						.equal("bpmnStatus", OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode())
						.equal("effectiveStatus", PlanEnums.EffectiveStatus.YES.getCode())
						.list();
				if (effectiveMpsVersions.size()==0){
					return Result.error("系统中未存在生效中的主计划版本，请先维护数据！");
				}

				lrpCoreService.clearAdvice();
				Context lrpContext = Context.defaultContext();
				lrpCoreService.initContext(lrpContext);
				lrpCoreService.runLrp();
				log.info("MRP:===========Job end============");
			}else{
				return Result.error("系统中存在正在执行中的MRP，请稍后再试！！");
			}
		} catch (Exception e) {
			log.error("MRP:===========Job Exception============");
			log.error(e.getMessage());
			e.printStackTrace();
			cacheProvider.del(MRP_CACHE_KEY);
		}
		cacheProvider.del(MRP_CACHE_KEY);
		return Result.OK("MRP结束！");
	}

	@GetMapping("list")
	@Operation(summary = "主计划版本列表", description = "获取主计划版本列表（无分页）", method = "GET")
	public Result<List<MpsVersion>> list(@Parameter(description = "查询参数") Criteria criteria)
			throws UnsupportedEncodingException {
		List<MpsVersion> mpsVersion = mpsVersionService.list(MpsVersion.class, criteria);
		return Result.OK(mpsVersion);
	}

	@GetMapping("po/page")
	@Operation(summary = "主计划未绑定销售订单行列表", description = "获取主计划未绑定销售订单行列表", method = "GET")
	public Result<Page<SalesOrderLine>> poList(@Parameter(description = "查询参数") Criteria criteria,
											   @Parameter(description = "主计划版本") String versionCode,
											   @Parameter(description = "每页条数") Integer pageSize,
											   @Parameter(description = "页号") Integer pageNo)
			throws UnsupportedEncodingException {
		Pageable page = PageRequest.of(pageNo - 1, pageSize);
		Page<SalesOrderLine> salesOrderLines = mpsVersionService.poLinePageWithoutMps(page, criteria, versionCode);
		return Result.OK(salesOrderLines);
	}

/*	@GetMapping("po/page")
	@Operation(summary = "销售订单行列表", description = "获取销售订单行列表", method = "GET")
	public Result<Page<SalesOrderLine>> poList(@Parameter(description = "查询参数") Criteria criteria,
											   @Parameter(description = "每页条数") Integer pageSize,
											   @Parameter(description = "页号") Integer pageNo)
			throws UnsupportedEncodingException {
		Pageable page = PageRequest.of(pageNo - 1, pageSize);
		Page<SalesOrderLine> salesOrderLines = mpsVersionService.poLinePage(page, criteria);
		return Result.OK(salesOrderLines);
	}*/

	@GetMapping("od/page")
	@Operation(summary = "主计划未绑定审核通过的组织需求行列表", description = "获取主计划未绑定组织需求行列表", method = "GET")
	public Result<Page<OrganizationDemandLine>> odList(@Parameter(description = "查询参数") Criteria criteria,
													   @Parameter(description = "主计划版本") String versionCode,
													   @Parameter(description = "每页条数") Integer pageSize,
													   @Parameter(description = "页号") Integer pageNo)
			throws UnsupportedEncodingException {
		Pageable page = PageRequest.of(pageNo - 1, pageSize);
		Page<OrganizationDemandLine> organizationDemandLines = mpsVersionService.odLinePageWithoutMps(page, criteria,versionCode);
		return Result.OK(organizationDemandLines);
	}

	@GetMapping("sp/page")
	@Operation(summary = "主计划未绑定审核通过的销售预测行列表", description = "获取主计划未绑定销售预测行列表", method = "GET")
	public Result<Page<SalePredictionLine>> spList(@Parameter(description = "查询参数") Criteria criteria,
													   @Parameter(description = "主计划版本") String versionCode,
													   @Parameter(description = "每页条数") Integer pageSize,
													   @Parameter(description = "页号") Integer pageNo)
			throws UnsupportedEncodingException {
		Pageable page = PageRequest.of(pageNo - 1, pageSize);
		criteria.addCriterion("closeStatus",Operator.NE, OrderStatusEnums.CloseStatus.CLOSED.getStatusCode());//过滤掉已关闭数据
		Page<SalePredictionLine> organizationDemandLines = mpsVersionService.spLinePageWithoutMps(page, criteria,versionCode);
		return Result.OK(organizationDemandLines);
	}

	@GetMapping("page")
	@Operation(summary = "主计划版本列表", description = "获取主计划版本列表（分页）", method = "GET")
	public Result<Page<MpsVersion>> page(@Parameter(description = "查询参数") Criteria criteria,
			@Parameter(description = "每页条数") Integer pageSize, @Parameter(description = "页号") Integer pageNo)
			throws UnsupportedEncodingException {
		Pageable page = PageRequest.of(pageNo - 1, pageSize);
		Page<MpsVersion> mpsVersion = mpsVersionService.listPage(MpsVersion.class, page, criteria);
		return Result.OK(mpsVersion);
	}

	@GetMapping("list/{id}")
	@Operation(summary = "根据id获取主计划版本", description = "根据id获取主计划版本", method = "GET")
	public Result<MpsVersion> getById(
			@Parameter(description = "ID") @PathVariable(name = "id", required = true) String id) {
		MpsVersion mpsVersion = mpsVersionService.getById(MpsVersion.class, id);
		return Result.OK(mpsVersion);
	}

	@RequestMapping("save")
	@Operation(summary = "保存主计划版本", description = "保存主计划版本")
	public Result<MpsVersion> save(@RequestBody MpsVersion mpsVersion) {
		Boolean result = mpsVersionService.saveOnCheck(mpsVersion);
		if(result){
			mpsVersionService.save(mpsVersion,new SmartCrudPolicyAdapter(){
				@Override
				public boolean beforeInsert(CrudContext context) {
					Object o = context.getEntity();
					if(o instanceof MpsLine){
						MpsVersion dbMpsVersion = context.getParent();
						((MpsLine) o).setVersionCode(dbMpsVersion.getCode());
						if (((MpsLine) o).getDataType().equals("03")){//预留
							SnRuleService snRuleService = SpringUtil.getBean(SnRuleService.class);
							String expression = "YL";
							String yearmonth = DateUtils.formatDate(new Date(), "yyyyMMdd");
							String bizNo = (String) snRuleService.execute(expression+yearmonth+"###", null);
							((MpsLine) o).setBizNo(bizNo);
							((MpsLine) o).setBizLineNo("1");
						}
					}
					return true;
				}
			});
			return Result.OK(mpsVersion);
		}else{
			return Result.error("保存失败，日期不符!");
		}
	}

	@DeleteMapping("remove/{ids}")
	@Operation(summary = "根据ids删除主计划版本", description = "删除主计划版本", method = "DELETE")
	@Transactional(readOnly = false)
	public Result<MpsVersion> remove(
			@Parameter(description = "id，多个单号用英文逗号分隔") @PathVariable(name = "ids", required = true) String ids) {
		String[] id = ids.split(",");
		for (String key : id) {
			mpsVersionService.delete(MpsVersion.class, key);
			Criteria c = Criteria.create().addCriterion("versionCode", Operator.EQ, key);
			List<MpsLine> mpsLineList = JpaUtil.linq(MpsLine.class).where(c).list();
			if (mpsLineList.size()>0){
				JpaUtil.delete(mpsLineList);//清空原主计划清单
			}
		}
		return Result.OK();
	}
	
	@PutMapping("submit/{id}")
    @Operation(summary = "提交主计划", description = "提交主计划", method = "PUT")
    public Result<MpsVersion> submit(@Parameter(description = "ID") @PathVariable(name = "id", required = true) String id) {
		MpsVersion mpsVersopm = mpsVersionService.getById(MpsVersion.class, id);
        if (mpsVersopm.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CREATE.getStatusCode())) {
            return mpsVersionService.updateBpmnStatus(mpsVersopm, OrderStatusEnums.BpmnStatus.AUDITING);
        } else {
            return Result.error("非开立状态不可提交");
        }
    }
	
	@PutMapping("audit/{id}")
    @Operation(summary = "审核主计划", description = "审核主计划", method = "PUT")
    public Result<MpsVersion> audit(@Parameter(description = "ID") @PathVariable(name = "id", required = true) String id) {
		MpsVersion mpsVersopm = mpsVersionService.getById(MpsVersion.class, id);
        if (mpsVersopm.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode())) {
            return mpsVersionService.updateBpmnStatus(mpsVersopm, OrderStatusEnums.BpmnStatus.AUDITED);
        } else {
            return Result.error("非审核中状态不可审核");
        }
    }

    @PutMapping("abandon/{id}")
    @Operation(summary = "弃审主计划", description = "弃审主计划", method = "PUT")
    public Result<MpsVersion> abandon(@Parameter(description = "ID") @PathVariable(name = "id", required = true) String id) {
    	MpsVersion mpsVersopm = mpsVersionService.getById(MpsVersion.class, id);
        if (mpsVersopm.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode()) || mpsVersopm.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode())) {
            return mpsVersionService.updateBpmnStatus(mpsVersopm, OrderStatusEnums.BpmnStatus.CREATE);
        } else {
            return Result.error("非审核中、已审核状态不可审核");
        }
    }

	@RequestMapping("change")
	@Operation(summary = "变更主计划", description = "变更主计划")
	@Transactional
	public Result<MpsVersion> change(@RequestBody MpsVersion mpsVersion) {
		MpsVersion db = mpsVersionService.getById(MpsVersion.class, mpsVersion.getCode());
		if (db.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode())) {
			//Result<MpsVersion> mpsVersionResult = mpsVersionService.updateBpmnStatus(mpsVersopm, OrderStatusEnums.BpmnStatus.AUDITED);
			List<MpsVersionTemp> list = JpaUtil.linq(MpsVersionTemp.class).equal("code", mpsVersion.getCode()).equal("bpmnStatus", OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode()).list();
			if (list.size()>0){
				return Result.error("存在待审核的变更数据，请处理后再执行变更操作！");
			}
			mpsVersionService.copyToTemp(mpsVersion);//复制数据到temp表中
			return Result.OK("变更成功，请处理对应的变更审核单",mpsVersion);
		} else {
			return Result.error("非已审核状态不可变更");
		}
	}
	@PutMapping("effect/{id}")
	@Operation(summary = "生效主计划", description = "生效主计划", method = "PUT")
	public Result<MpsVersion> effect(@Parameter(description = "ID") @PathVariable(name = "id", required = true) String id) {
		MpsVersion mpsVersopm = mpsVersionService.getById(MpsVersion.class, id);
		if (mpsVersopm.getEffectiveStatus().equals(CommonEnums.EffectiveStatus.NO.getCode())) {
			return mpsVersionService.updateEffectiveStatus(mpsVersopm, CommonEnums.EffectiveStatus.YES);
		} else {
			return Result.error("主计划已经是生效状态，不能重复执行生效操作。");
		}
	}
}
